import { V_UnderV8 } from "./version";

// 制作一个自己封装的promise 主要解决node8上面没有finally
class TePromise<T> {
    pm: Promise<T>

    thenPools: ((v: any) => any)[] = [];
    catchPools: ((e: any) => any)[] = [];
    finallPools: (() => any)[] = [];

    constructor(cb: any) {
        if (cb instanceof Promise) {
            this.pm = cb
        }
        else {
            this.pm = new Promise(cb)
        }

        this.pm.then(this.onThen.bind(this)).catch(this.onCatch.bind(this))

        this.pm.then = this.then.bind(this) as any
        this.pm.catch = this.catch.bind(this) as any
        this.pm.finally = this.finally.bind(this) as any
    }

    private onThen(v: any) {
        // 这里按照列表一个一个来出现异常就进入catch
        try {
            var fn = this.thenPools.shift()
            while (fn) {
                fn(v)
                fn = this.thenPools.shift()
            }
        }
        catch (e) {
            this.onCatch(e)
        }
        finally {
            this.doFinally()
        }
    }

    private onCatch(e: any) {
        try {
            var fn = this.catchPools.shift()
            while (fn) {
                fn(e)
                fn = this.catchPools.shift()
            }
        }
        catch (e) {

        }
        finally {
            this.doFinally()
        }
    }

    private doFinally() {
        var fn = this.finallPools.shift();
        while (fn) {
            fn()
            fn = this.finallPools.shift()
        }
    }

    private then(onReslove: (v: any) => any, onReject?: (reason: any) => any) {
        this.thenPools.push(onReslove)
        if (onReject) this.catchPools.push(onReject)
        return this;
    }

    private catch(cb: (e: any) => any) {
        this.catchPools.push(cb)
        return this;
    }

    private finally(cb: () => any) {
        this.finallPools.push(cb)
        return this;
    }

}

export function createPromise(func: any) {
    if (V_UnderV8) {
        return (new TePromise<any>(func)).pm
    }
    else {
        if (func instanceof Promise)
            return func
        else
            return new Promise<any>(func)
    }
}